/*
@title: GameForNoInternet
@description: "GameForNoInternet" is an endless runner game where players must jump over obstacles to accumulate points.
@author: Souptik Samanta
@tags: ['endless']
@addedOn: 2024-10-12
*/


let mapHeight = 10;
const mapWidth = 20;

// Game need variables
let isPlaying = true;
let gameScore = 0;


const dino = "d";
const dinoAlt = "D";
const obstacle = "x";
const obstacleAlt = "X";
const cloudSprite = "s";
const groundSprite = "g";

setLegend(
  [dino, bitmap`
.....666........
....6006666.....
...60000226.....
...60000226.....
...60000066.....
..6000000677....
666000007.7.....
00000000777.....
0000000077......
00000000777.....
000066666.77....
00006...........
000066..........
000777..........
0007.777........
0077...7........`],
  [dinoAlt, bitmap`
.....666........
....6006666.....
...60000226.....
...60000226.....
...60000066.....
..6000000677....
666000007.7.....
00000000777.....
0000000077......
00000000777.....
000066666.77....
00006...........
000066..........
000777..........
0007.777........
0077...7........`],
  [obstacle, bitmap`
................
................
................
......3333......
.....3CC003.....
....3CCC0203....
....3CCC00033...
....3CCC00003...
....3F.F.FFF3...
....3FFFFFFF3...
.LLLLFFFFFFF3...
.LLL333333333...
.000333333333...
.LLL33333333....
.LLL3333.333....
....3333.333....`],
  [obstacleAlt, bitmap`
................
................
................
......3333......
.....3CC003.....
....3CCC0203....
....3CCC00033...
....3CCC00003...
....3F.F.FFF3...
....3FFFFFFF3...
.LLLLFFFFFFF3...
.LLL333333333...
.000333333333...
.LLL33333333....
.LLL3333.333....
....3333.333....`],
  [cloudSprite, bitmap`
..................
........1111......
.....111.7.7111...
....11..7..7111...
..111...77777111..
11777777777771111.
.1111....11111111.
..................
..................
..................
..................
..................
..................
..................
..................
..................`],
  [groundSprite, bitmap`
................
................
................
................
................
................
................
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444
4444444444444444`]
);


const generateGround = () => groundSprite.repeat(mapWidth);

const generateSky = () => ".".repeat(mapWidth);

const generateSkyWithClouds = () => {
  let layer = "";
  for (let i = 0; i < mapWidth; i++) {
    if (Math.random() < 0.15) {
      layer += cloudSprite;
    } else {
      layer += ".";
    }
  }
  return layer;
};


const createPlayerLayer = () => {
  let layer = "." + dino;
  for (let i = layer.length; i < mapWidth; i++) {
    layer += ".";
  }
  return layer;
};


let mapLayers = [];

for (let i = 0; i < 3; i++) {
  mapLayers.push(generateSkyWithClouds());
}
for (let i = 0; i < 4; i++) {
  mapLayers.push(generateSky());
}
mapLayers.push(createPlayerLayer());
mapLayers.push(generateGround());
mapLayers.push(generateGround());


setMap(mapLayers.join("\n"));

let isJumping = false;
let jumpHeight = 0;
let jumpVelocity = 1;


const getPlayer = () => getFirst(dino) ? getFirst(dino) : getFirst(dinoAlt);


onInput("w", () => {
  if (!isJumping) {
    isJumping = true;
  }
});


setInterval(() => {
  if (isPlaying) {
    clearText();
    addText(gameScore.toString(), { x: 1, y: 4, color: color`0` });
    gameScore++;

  
    for (let i = 0; i < 3; i++) {
      let layer = mapLayers[i].substring(1);
      layer += Math.random() < 0.15 ? cloudSprite : ".";
      mapLayers[i] = layer;
    }

 
    mapLayers[7] = mapLayers[7].substring(1);
    if (Math.random() < 0.1) {
      mapLayers[7] += Math.random() < 0.5 ? obstacle : obstacleAlt;
    } else {
      mapLayers[7] += ".";
    }

    
    const checkCollision = (obs) => {
      if (obs.x == 2 && getPlayer().y == 7) {
        isPlaying = false;
        addText("Game Over!", { x: 7, y: 4, color: color`0` });
      }
    };

    getAll(obstacle).forEach(checkCollision);
    getAll(obstacleAlt).forEach(checkCollision);

    // Manage jump physics
    if (isJumping) {
      jumpHeight += jumpVelocity;
      if (jumpHeight == 3) {
        jumpVelocity = -1;
      }
      if (jumpHeight == -1) {
        isJumping = false;
        jumpHeight = 0;
        jumpVelocity = 1;
      }
    }

    
    for (let i = 4; i < 7; i++) {
      mapLayers[i] = generateSky();
    }

    mapLayers[7] = mapLayers[7].replace(dino, ".").replace(dinoAlt, ".");
    mapLayers[7 - jumpHeight] =
      mapLayers[7 - jumpHeight].substring(0, 1) +
      (gameScore % 2 == 0 ? dino : dinoAlt) +
      mapLayers[7 - jumpHeight].substring(2);
    
    setMap(mapLayers.join("\n"));
  }
}, 90); //Here the speed of game is adujstable you may increase this if you want to play in increased seep and vice versa
